package com.lz.helper.face

import android.util.Log
import com.face.FaceRecognize
import java.util.concurrent.atomic.AtomicBoolean

//照相机人脸检测
class CameraOperator(
    private val w: Int,
    private val h: Int,
    private val timeout: Long,
    private val handler: CameraHandler
) : Runnable {

    companion object {

        private const val TAG = "CameraOperator"

        //未检测出人脸
        const val ERR_DETECT = 1

        //未检测出人脸特征值
        const val ERR_FEATURE = 1
    }

    //要处理的数据, 缓存
    private val buffer: ByteArray = ByteArray(w * h * 3 / 2)

    //是否暂停, 暂停时将线程挂起
    private var isPaused = false

    //是否退出
    private val quit = AtomicBoolean(false)

    //是否正在识别
    private var isCoding = false

    //锁
    private val async = Object()

    //匹配请求与匹配时间
    private var request: FeatureRequest? = null
    private var requestTime: Long = 0L

    //当前是否已经有匹配
    private var isFeaturing = false

    //暂停
    fun pause() {
        synchronized(async) { isPaused = true }
    }

    //恢复
    fun restart() {
        synchronized(async) { isPaused = false; async.notify() }
    }

    //中断退出
    fun quit() {
        synchronized(async) { quit.set(true); async.notify() }
    }

    fun pushNvData(nvData: ByteArray) {
        synchronized(async) {
            if (isPaused || isCoding || quit.get()) return
            System.arraycopy(nvData, 0, buffer, 0, nvData.size)
            isCoding = true
            async.notify()
        }
    }

    private fun synWait() {
        synchronized(async) {
            while (!quit.get() &&(!isCoding || isPaused)) {
                try {
                    async.wait()
                } catch (_: InterruptedException) {
                }
            }
        }
    }

    //解码完
    private fun codingOver() {
        synchronized(this) {
            if (checkRequest()) {
                isFeaturing = false
            }
        }
        synchronized(async) {
            isCoding = false
        }
    }

    @Synchronized
    fun pushFeatureRequest(request: FeatureRequest): Boolean {
        Log.d(TAG, "pushFeatureRequest $isFeaturing")
        if (isFeaturing) return false
        this.isFeaturing = true
        this.request = request
        this.requestTime = System.currentTimeMillis()
        return true
    }

    //检测匹配请求是否超时
    private fun checkRequest(): Boolean {
        if (request == null) return true
        val currTime = System.currentTimeMillis()
        if (currTime - requestTime > timeout) {
            Log.d(TAG, "checkRequest timeout and setFeature false......")
            request!!.timeout()
            request = null
            return true
        }
        return false
    }

    override fun run() {
        while (!quit.get()) {
            synWait()
            if (quit.get()) break

            //检测NV数据
            val detect = FaceRecognize.getInstance().detectFace(buffer, w, h, FaceRecognize.IMAGE_TYPE_NV21)
            Log.d(TAG, "...... camera detectFace ${detect?.size ?: 0} ......")
            if (quit.get()) break
            if (detect == null || detect.size <= 1) {
                codingOver()
                handler.sendError(ERR_DETECT)
                continue
            }
            handler.sendDetectSuccess(detect)

            Log.d(TAG, "...... camera featureExtract before......")
            //检测特征值并匹配
            val feature = FaceRecognize.getInstance().featureExtract(buffer, w, h, detect, FaceRecognize.IMAGE_TYPE_NV21)
            Log.d(TAG, "...... camera featureExtract ${feature?.size ?: 0} ......")
            if (quit.get()) break
            if (feature == null || feature.isEmpty()) {
                codingOver()
                handler.sendError(ERR_FEATURE)
                continue
            }

            //匹配请求处理
            val isFeaturing = synchronized(this) {
                this.isFeaturing
            }
            Log.d(TAG, "feature and is Featuring = $isFeaturing")
            //匹配请求
            if (isFeaturing) {
                if(request!!.recognize(buffer, feature, w, h) >= 0) {
                    request = null
                }
                if (quit.get()) break
            }
            codingOver()
        }
        Log.i(TAG, "CameraOperator quit......")
    }

    interface CameraHandler {

        //检测轮廓成功
        fun sendDetectSuccess(detect: IntArray)

        //异常
        fun sendError(status: Int)
    }
}